/**
*********************************************************************************************************
*               Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved.
**********************************************************************************************************
* @file
* @brief
* @details
* @author
* @date
* @version
*********************************************************************************************************
*/

/* Includes ------------------------------------------------------------------*/
#include "rtl876x_gpio_i2c_wristband.h"
#include "rtl876x_i2c.h"
#include "rtl876x_rcc.h"
#include "rtl876x_gpio.h"
#include "trace.h"
#include "platform_utils.h"
#include "rtl876x_pinmux.h"
#include "rtl876x_tim.h"
#include "rtl876x_nvic.h"
#define IIC_MAX_TIMEOUT_US      1000
#define SCL_HOLD      1
/*******************************************
Init Example usage
GPIO_I2C_InitTypeDef  GPIO_I2C_InitStructure;
void gpio_i2c_driver_init()
{
    GPIO_I2C_StructInit(&GPIO_I2C_InitStructure);
    GPIO_I2C_InitStructure.I2C_ClockSpeed   = 100000;
    GPIO_I2C_InitStructure.I2C_AddressMode  = I2C_AddressMode_7BIT;
    GPIO_I2C_InitStructure.I2C_SlaveAddress = TOUCH_SLAVE_ADDRESS;
    GPIO_I2C_InitStructure.I2C_SDA_Pin = TOUCH_I2C_SDA;
    GPIO_I2C_InitStructure.I2C_SCL_Pin = TOUCH_I2C_SCL;
    GPIO_I2C_Init(&GPIO_I2C_InitStructure);

}
*******************************************/
/**
  * @brief  Deinitializes the I2Cx peripheral registers to their default reset values.
  * @param  I2Cx: where x can be 0 or 1 to select the I2C peripheral.
  * @retval None
  */
void GPIO_I2C_DeInit(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    Pad_Config(GPIO_I2C_InitStruct->I2C_SCL_Pin, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_UP,
               PAD_OUT_DISABLE, PAD_OUT_HIGH);
    Pad_Config(GPIO_I2C_InitStruct->I2C_SDA_Pin, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_UP,
               PAD_OUT_DISABLE, PAD_OUT_HIGH);
}
__STATIC_INLINE void GPIO_I2C_SET_SCL(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
//    GPIO_SetBits(GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SCL_Pin));
    GPIO_SetBits( GPIO_I2C_InitStruct->xI2C_SCL_Pin );
}

__STATIC_INLINE void GPIO_I2C_RESET_SCL(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
//    GPIO_ResetBits(GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SCL_Pin));
    GPIO_ResetBits( GPIO_I2C_InitStruct->xI2C_SDA_Pin );
}

__STATIC_INLINE void GPIO_I2C_SET_SDA(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
//    GPIO_SetBits(GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin));
    GPIO_SetBits( GPIO_I2C_InitStruct->xI2C_SDA_Pin );
}

__STATIC_INLINE void GPIO_I2C_RESET_SDA(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
//    GPIO_ResetBits(GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin));
    GPIO_ResetBits( GPIO_I2C_InitStruct->xI2C_SDA_Pin );
}
__STATIC_INLINE void GPIO_I2C_free_SCL(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
//    GPIO->DATADIR = GPIO->DATADIR & (~GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SCL_Pin));
    GPIO->DATADIR = GPIO->DATADIR & (~GPIO_I2C_InitStruct->xI2C_SCL_Pin);
}
__STATIC_INLINE void GPIO_I2C_OUT_SCL(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
//    GPIO->DATADIR |= GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SCL_Pin);
//    GPIO->DATASRC &= (~GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SCL_Pin));
    GPIO->DATADIR |= GPIO_I2C_InitStruct->xI2C_SCL_Pin;
    GPIO->DATASRC &= (~GPIO_I2C_InitStruct->xI2C_SCL_Pin);    
}
__STATIC_INLINE void GPIO_I2C_free_SDA(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
//    GPIO->DATADIR = GPIO->DATADIR & (~GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin));
    GPIO->DATADIR = GPIO->DATADIR & (~GPIO_I2C_InitStruct->xI2C_SDA_Pin);
}
__STATIC_INLINE void GPIO_I2C_OUT_SDA(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
//    GPIO->DATADIR |= GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin);
//    GPIO->DATASRC &= (~GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin));
    GPIO->DATADIR |= GPIO_I2C_InitStruct->xI2C_SDA_Pin;
    GPIO->DATASRC &= (~GPIO_I2C_InitStruct->xI2C_SDA_Pin);
}

__STATIC_INLINE bool __wait_while_scl_low(  GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct )
{
    GPIO_I2C_free_SCL( GPIO_I2C_InitStruct );
    GPIO_I2C_SET_SCL( GPIO_I2C_InitStruct );
    int timeout = IIC_MAX_TIMEOUT_US;
    
    while( (GPIO->DATAIN & GPIO_I2C_InitStruct->xI2C_SCL_Pin ) == 0  && (timeout --)  );
    GPIO_I2C_OUT_SCL( GPIO_I2C_InitStruct );
    
    return ( timeout != 0 );        
}

__STATIC_INLINE void GPIO_I2C_start(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    GPIO_I2C_OUT_SCL( GPIO_I2C_InitStruct );
    GPIO_I2C_OUT_SDA( GPIO_I2C_InitStruct );
    
//    GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
    
    __wait_while_scl_low( GPIO_I2C_InitStruct );       

    GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
    platform_delay_us(GPIO_I2C_InitStruct->delay);
    GPIO_I2C_RESET_SCL( GPIO_I2C_InitStruct ); 
}

__STATIC_INLINE void GPIO_I2C_stop(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
    
    GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
    platform_delay_us(GPIO_I2C_InitStruct->delay);
    
    GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
    platform_delay_us(GPIO_I2C_InitStruct->delay);    
    GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
}
static bool GPIO_I2C_wait_ack(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    uint16_t timeout = IIC_MAX_TIMEOUT_US;
    GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
    while (timeout--)
    {
//        if ((GPIO->DATAOUT & GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SCL_Pin)) == RESET)
        if ((GPIO->DATAOUT & GPIO_I2C_InitStruct->xI2C_SCL_Pin) == RESET)
        {
            GPIO_I2C_free_SDA(GPIO_I2C_InitStruct);
            break;
        }
    }
    if (timeout == 0)
    {
        GPIO_I2C_free_SCL(GPIO_I2C_InitStruct);
        GPIO_I2C_free_SDA(GPIO_I2C_InitStruct);
        return false;
    }
    platform_delay_us(GPIO_I2C_InitStruct->delay);

    GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);


    timeout = IIC_MAX_TIMEOUT_US;
    while (timeout--)
    {
//        if ((GPIO->DATAIN & GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin)) == RESET)
        if ((GPIO->DATAIN & GPIO_I2C_InitStruct->xI2C_SDA_Pin) == RESET)
        {
            platform_delay_us(GPIO_I2C_InitStruct->delay);
            return true;
        }
    }
    return false;
}

__STATIC_INLINE void GPIO_I2C_send_ack(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
    GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
    platform_delay_us(GPIO_I2C_InitStruct->delay);
    GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
    platform_delay_us(GPIO_I2C_InitStruct->delay);
}
__STATIC_INLINE void GPIO_I2C_send_nack(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
    GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
    platform_delay_us(GPIO_I2C_InitStruct->delay);
    GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
    platform_delay_us(GPIO_I2C_InitStruct->delay);
}
__STATIC_INLINE void GPIO_I2C_Configuration(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    Pad_Config(GPIO_I2C_InitStruct->I2C_SCL_Pin, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP,
               PAD_OUT_ENABLE, PAD_OUT_HIGH);
    Pad_Config(GPIO_I2C_InitStruct->I2C_SDA_Pin, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP,
               PAD_OUT_ENABLE, PAD_OUT_HIGH);

    Pinmux_Config(GPIO_I2C_InitStruct->I2C_SCL_Pin, DWGPIO);
    Pinmux_Config(GPIO_I2C_InitStruct->I2C_SDA_Pin, DWGPIO);
    
    GPIO_I2C_InitStruct->xI2C_SCL_Pin = GPIO_GetPin( GPIO_I2C_InitStruct->I2C_SCL_Pin );
    GPIO_I2C_InitStruct->xI2C_SDA_Pin = GPIO_GetPin( GPIO_I2C_InitStruct->I2C_SDA_Pin );
}
__STATIC_INLINE void GPIO_I2C_BusClear(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    GPIO_I2C_OUT_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
    GPIO_I2C_stop(GPIO_I2C_InitStruct);
    GPIO_I2C_free_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_free_SDA(GPIO_I2C_InitStruct);
    GPIO_I2C_InitStruct->busy_flag = false;
}
/**
  * @brief  check GPIO_I2C_InitTypeDef.
  * @param  GPIO_I2C_InitTypeDef : pointer to a GPIO_I2C_InitTypeDef structure which will be initialized.
  * @retval false error.
  */
bool GPIO_I2C_CheckStructStatus(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    if ((GPIO_I2C_InitStruct->I2C_ClockSpeed > 400000) |
        (GPIO_I2C_InitStruct->I2C_AddressMode > I2C_AddressMode_10BIT) |
        (GPIO_I2C_InitStruct->I2C_SlaveAddress > 0x400) |
        (GPIO_I2C_InitStruct->I2C_SDA_Pin > H_2) |
        (GPIO_I2C_InitStruct->I2C_SCL_Pin > H_2)
       )
    {
        return false;
    }
    return true;
}

/**
  * @brief  Initializes the GPIO_I2C peripheral according to the specified
  *   parameters in the GPIO_I2C_InitStruct.
  * @param  GPIO_I2C_InitStruct: pointer to a I2C_InitTypeDef structure that
  *   contains the configuration information for the specified GPIO_I2C peripheral.
  * @retval None
  */
void GPIO_I2C_Init(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    if (GPIO_I2C_CheckStructStatus(GPIO_I2C_InitStruct) == false)
    {
        APP_PRINT_INFO0("GPIO_I2C Check Struct Status error");
    }
    GPIO_I2C_Configuration(GPIO_I2C_InitStruct);
    RCC_PeriphClockCmd(APBPeriph_GPIO, APBPeriph_GPIO_CLOCK, ENABLE);
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin    = GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SCL_Pin) |
                                  GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin);
    GPIO_InitStruct.GPIO_Mode   = GPIO_Mode_OUT;
    GPIO_InitStruct.GPIO_ITCmd  = DISABLE;
    GPIO_Init(&GPIO_InitStruct);
    GPIO_I2C_InitStruct->delay = 400000 / GPIO_I2C_InitStruct->I2C_ClockSpeed;
}

/**
  * @brief  Fills each GPIO_I2C_InitTypeDef member with its default value.
  * @param  GPIO_I2C_InitTypeDef : pointer to a GPIO_I2C_InitTypeDef structure which will be initialized.
  * @retval None
  */
void GPIO_I2C_StructInit(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    GPIO_I2C_InitStruct->I2C_ClockSpeed = 400000;      /*!< Specifies the clock frequency.
                                                This parameter must be set to a value lower than 400kHz */
    GPIO_I2C_InitStruct->I2C_AddressMode =
        I2C_AddressMode_7BIT;     /*!< Specifies the I2C address mode.
                                                This parameter can be a value of @ref I2C_address_mode */

    GPIO_I2C_InitStruct->I2C_SlaveAddress = 0;    /*!< Specifies the first device own address.
                                                This parameter can be a 7-bit or 10-bit address. */
    GPIO_I2C_InitStruct->I2C_SDA_Pin = 0;
    GPIO_I2C_InitStruct->I2C_SCL_Pin = 0;
    GPIO_I2C_InitStruct->delay = 2;
    GPIO_I2C_InitStruct->busy_flag = 0;
}

bool GPIO_I2C_BUS_CHECK(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    bool ret = SET;
    GPIO_I2C_free_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_free_SDA(GPIO_I2C_InitStruct);
    ret = ret & GPIO_ReadInputDataBit(GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SCL_Pin));
    ret = ret & GPIO_ReadInputDataBit(GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin));
    GPIO_I2C_OUT_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
    return !ret;
}
bool GPIO_I2C_SCL_HOLD_CHECK(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    return GPIO_ReadInputDataBit(GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SCL_Pin));
}
/**
  * @brief  Send data in master mode through the GPIO_I2C peripheral.
  * @param  I2Cx: where x can be 0 or 1 to select the GPIO_I2C peripheral.
  * @param  Data: Byte to be transmitted..
  * @retval None
  */

GPIO_I2C_Status GPIO_I2C_MasterWrite(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct, uint8_t *pBuf,
                                     uint16_t len)
{
    uint8_t shift;
    uint8_t address_len;
    uint16_t address_data;
    uint16_t index;
    if (GPIO_I2C_CheckStructStatus(GPIO_I2C_InitStruct) == false)
    {
        APP_PRINT_INFO0("GPIO_I2C Check Struct Status error");
        return I2C_GPIO_INVALUE;
    }
    if (GPIO_I2C_InitStruct->busy_flag)

    {
        return I2C_GPIO_BUSY;
    }
    GPIO_I2C_InitStruct->busy_flag = true;
    if (GPIO_I2C_BUS_CHECK(GPIO_I2C_InitStruct))
    {
        GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
        return I2C_GPIO_BUSY;
    }


    GPIO_I2C_start(GPIO_I2C_InitStruct);
    if (GPIO_I2C_InitStruct->I2C_AddressMode)
    {
        address_data = (((GPIO_I2C_InitStruct->I2C_SlaveAddress >> 7) & 0xf6) | 0xf0) |
                       (GPIO_I2C_InitStruct->I2C_SlaveAddress << 8);
    }
    else
    {
        address_data = (GPIO_I2C_InitStruct->I2C_SlaveAddress << 1) & 0xfe;
    }
    for (address_len = 0; address_len < GPIO_I2C_InitStruct->I2C_AddressMode + 1; address_len++)
    {

        for (shift = 0; shift < 8; shift ++)
        {
            GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
            GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
            if (((address_data >> address_len * 8) >> (7 - shift)) & 0x01)
            {
                GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
            }
            else
            {
                GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
            }
            platform_delay_us(GPIO_I2C_InitStruct->delay);


            GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
            platform_delay_us(GPIO_I2C_InitStruct->delay);
        }
        if (GPIO_I2C_wait_ack(GPIO_I2C_InitStruct) == 0)
        {
            GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
            return I2C_GPIO_ADDR_NOACK;
        }
    }
    for (index = 0; index < len; index++)
    {
        for (shift = 0; shift < 8; shift ++)
        {
#if SCL_HOLD
            uint16_t timeout = IIC_MAX_TIMEOUT_US;
            GPIO_I2C_free_SCL(GPIO_I2C_InitStruct);
            while (timeout--)
            {
                if (GPIO_I2C_SCL_HOLD_CHECK(GPIO_I2C_InitStruct))
                {
                    break;
                }
            }
            if (timeout == 0)
            {
                GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
                return I2C_GPIO_ERR_TIMEOUT;
            }
            GPIO_I2C_OUT_SCL(GPIO_I2C_InitStruct);
#endif
            GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
            GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
            if (((*(pBuf + index)) >> (7 - shift)) & 0x01)
            {
                GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
            }
            else
            {
                GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
            }
            platform_delay_us(GPIO_I2C_InitStruct->delay);
            GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
            platform_delay_us(GPIO_I2C_InitStruct->delay);
        }
        if (GPIO_I2C_wait_ack(GPIO_I2C_InitStruct) == 0)
        {
            GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
            return I2C_GPIO_TXDATA_NOACK;
        }
    }

    GPIO_I2C_stop(GPIO_I2C_InitStruct);
    GPIO_I2C_InitStruct->busy_flag = false;
    return I2C_GPIO_Success;
}

GPIO_I2C_Status GPIO_I2C_MasterRead(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct, uint8_t *pBuf,
                                    uint16_t len)
{
    uint8_t shift;
    uint8_t address_len;
    uint16_t address_data;
    uint16_t index;
    if (GPIO_I2C_CheckStructStatus(GPIO_I2C_InitStruct) == false)
    {
        APP_PRINT_INFO0("GPIO_I2C Check Struct Status error");
        return I2C_GPIO_INVALUE;
    }
    if (GPIO_I2C_InitStruct->busy_flag)
    {
        return I2C_GPIO_BUSY;
    }
    GPIO_I2C_InitStruct->busy_flag = true;
    if (GPIO_I2C_BUS_CHECK(GPIO_I2C_InitStruct))
    {
        GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
        return I2C_GPIO_BUSY;
    }

    GPIO_I2C_start(GPIO_I2C_InitStruct);

    if (GPIO_I2C_InitStruct->I2C_AddressMode)
    {
        address_data = (((GPIO_I2C_InitStruct->I2C_SlaveAddress >> 7) & 0xf6) | 0xf1) |
                       (GPIO_I2C_InitStruct->I2C_SlaveAddress << 8);
    }
    else
    {
        address_data = (GPIO_I2C_InitStruct->I2C_SlaveAddress << 1) | 0x01;
    }
    for (address_len = 0; address_len < GPIO_I2C_InitStruct->I2C_AddressMode + 1; address_len++)
    {

        for (shift = 0; shift < 8; shift ++)
        {
            GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
            GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
            if (((address_data >> address_len * 8) >> (7 - shift)) & 0x01)
            {
                GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
            }
            else
            {
                GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
            }
            platform_delay_us(GPIO_I2C_InitStruct->delay);


            GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
            platform_delay_us(GPIO_I2C_InitStruct->delay);
        }
        if (GPIO_I2C_wait_ack(GPIO_I2C_InitStruct) == 0)
        {
            GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
            return I2C_GPIO_ADDR_NOACK;
        }
    }

    for (index = 0; index < len; index++)
    {

        for (shift = 0; shift < 8; shift ++)
        {
#if SCL_HOLD
            uint16_t timeout = IIC_MAX_TIMEOUT_US;
            GPIO_I2C_free_SCL(GPIO_I2C_InitStruct);
            while (timeout--)
            {
                if (GPIO_I2C_SCL_HOLD_CHECK(GPIO_I2C_InitStruct))
                {
                    break;
                }
            }
            if (timeout == 0)
            {
                GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
                return I2C_GPIO_ERR_TIMEOUT;
            }
            GPIO_I2C_OUT_SCL(GPIO_I2C_InitStruct);
#endif
            GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
            GPIO_I2C_free_SDA(GPIO_I2C_InitStruct);
            platform_delay_us(GPIO_I2C_InitStruct->delay);
            GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
            platform_delay_us(GPIO_I2C_InitStruct->delay);
            if ((GPIO->DATAIN & GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin)))
            {
                *(pBuf + index) |= BIT(7 - shift);
            }
            else
            {
                *(pBuf + index) &= ~BIT(7 - shift);
            }
        }
        if (index == len - 1)
        {
            GPIO_I2C_send_nack(GPIO_I2C_InitStruct);
        }
        else
        {
            GPIO_I2C_send_ack(GPIO_I2C_InitStruct);
        }
    }
    GPIO_I2C_stop(GPIO_I2C_InitStruct);
    GPIO_I2C_InitStruct->busy_flag = false;
    return I2C_GPIO_Success;


}

GPIO_I2C_Status GPIO_I2C_RepeatRead(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct, uint8_t *pWriteBuf,
                                    uint16_t Writelen,
                                    uint8_t *pReadBuf, uint16_t Readlen)
{
    uint8_t shift;
//    uint8_t address_len;
    uint16_t address_data;
    uint8_t index;

    if( GPIO_I2C_CheckStructStatus(GPIO_I2C_InitStruct) == false) 
    {
        APP_PRINT_INFO0("GPIO_I2C Check Struct Status error");
        return I2C_GPIO_INVALUE;
    }
    // if( GPIO_I2C_InitStruct->busy_flag )
    // {
    //     return I2C_GPIO_BUSY;
    // }
    // GPIO_I2C_InitStruct->busy_flag = true;
    // if( GPIO_I2C_BUS_CHECK( GPIO_I2C_InitStruct ) )
    // {
    //     GPIO_I2C_BusClear( GPIO_I2C_InitStruct );
    //     return I2C_GPIO_BUSY;
    // }
    
    GPIO_I2C_start( GPIO_I2C_InitStruct );   
    address_data = (GPIO_I2C_InitStruct->I2C_SlaveAddress << 1) & 0xfe;
    for( shift = 0; shift < 8; shift ++ )
    {
        GPIO_I2C_RESET_SCL( GPIO_I2C_InitStruct );
        GPIO_I2C_OUT_SDA( GPIO_I2C_InitStruct );
        if( (address_data >> (7-shift)) & 0x01  )
        {
            GPIO_I2C_SET_SDA( GPIO_I2C_InitStruct );
        }
        else 
        {
            GPIO_I2C_RESET_SDA( GPIO_I2C_InitStruct );
        }
        platform_delay_us( GPIO_I2C_InitStruct->delay );     

        GPIO_I2C_SET_SCL( GPIO_I2C_InitStruct ) ;
        platform_delay_us( GPIO_I2C_InitStruct->delay );  
    }
    if( GPIO_I2C_wait_ack( GPIO_I2C_InitStruct) == 0 )
    {
        GPIO_I2C_BusClear( GPIO_I2C_InitStruct );
        return I2C_GPIO_ADDR_NOACK;
    }
    for( index = 0; index < Writelen; index ++ )
    {
        for( shift = 0; shift < 8; shift ++ )
        {
            #if 1 // check SCL
            uint16_t timeout = IIC_MAX_TIMEOUT_US;
            GPIO_I2C_free_SCL( GPIO_I2C_InitStruct );
            while( timeout -- )
            {
                if( GPIO_I2C_SCL_HOLD_CHECK( GPIO_I2C_InitStruct ) )
                {
                    break;
                }
            }
            if( timeout == 0 ) 
            {
                GPIO_I2C_BusClear( GPIO_I2C_InitStruct );
                return I2C_GPIO_ERR_TIMEOUT;
            }
            
            GPIO_I2C_OUT_SCL( GPIO_I2C_InitStruct );
            #endif 
            
            GPIO_I2C_RESET_SCL( GPIO_I2C_InitStruct );
            GPIO_I2C_OUT_SDA( GPIO_I2C_InitStruct );
            if( (pWriteBuf[index] >> (7-shift)) & 0x01 )
            {
                GPIO_I2C_SET_SDA( GPIO_I2C_InitStruct );
            }
            else 
            {
                GPIO_I2C_RESET_SDA( GPIO_I2C_InitStruct );
            }
            platform_delay_us( GPIO_I2C_InitStruct->delay );
            GPIO_I2C_SET_SCL( GPIO_I2C_InitStruct );
            platform_delay_us( GPIO_I2C_InitStruct->delay );
        }
        if( GPIO_I2C_wait_ack( GPIO_I2C_InitStruct) == 0 )
        {
            GPIO_I2C_BusClear( GPIO_I2C_InitStruct );
            return I2C_GPIO_TXDATA_NOACK;
        }
    }
    
    // restart 
    GPIO_I2C_start( GPIO_I2C_InitStruct );
    address_data = (GPIO_I2C_InitStruct->I2C_SlaveAddress << 1 ) | 0x01;
    for( shift = 0; shift <8; shift ++ )
    {
        GPIO_I2C_RESET_SCL( GPIO_I2C_InitStruct );
        GPIO_I2C_OUT_SDA( GPIO_I2C_InitStruct );
        if( (address_data >> (7-shift)) & 0x01 )
        {
            GPIO_I2C_SET_SDA( GPIO_I2C_InitStruct );
        }
        else 
        {
            GPIO_I2C_RESET_SDA( GPIO_I2C_InitStruct );
        }
        platform_delay_us( GPIO_I2C_InitStruct->delay );  
        
        GPIO_I2C_SET_SCL( GPIO_I2C_InitStruct ) ;
        platform_delay_us( GPIO_I2C_InitStruct->delay );        
    }
    if( GPIO_I2C_wait_ack( GPIO_I2C_InitStruct) == 0 )
    {
        GPIO_I2C_BusClear( GPIO_I2C_InitStruct );
        return I2C_GPIO_ADDR_NOACK;
    }
    
    for( index = 0; index < Readlen; index ++ )
    {
        for(shift = 0; shift < 8; shift ++ )
        {
            #if 1 // check SCL
            uint16_t timeout = IIC_MAX_TIMEOUT_US;
            GPIO_I2C_free_SCL( GPIO_I2C_InitStruct );
            while( timeout -- ) 
            {
                if( GPIO_I2C_SCL_HOLD_CHECK( GPIO_I2C_InitStruct ) )
                {
                    break;
                }
            }
            if( timeout == 0 ) 
            {
                GPIO_I2C_BusClear( GPIO_I2C_InitStruct );
                return I2C_GPIO_ERR_TIMEOUT;
            }
            GPIO_I2C_OUT_SCL( GPIO_I2C_InitStruct );
            #endif 
            
            GPIO_I2C_RESET_SCL( GPIO_I2C_InitStruct );
            GPIO_I2C_free_SDA( GPIO_I2C_InitStruct );
            platform_delay_us( GPIO_I2C_InitStruct->delay );
            GPIO_I2C_SET_SCL( GPIO_I2C_InitStruct );
            platform_delay_us( GPIO_I2C_InitStruct->delay );
            pReadBuf[index] <<= 1; 
            if( (GPIO->DATAIN & GPIO_GetPin( GPIO_I2C_InitStruct->I2C_SDA_Pin ) ))
            {
                pReadBuf[index] |= 0x01;
            }            
        }
        if( index == ( Readlen - 1 ) )
        {
            GPIO_I2C_send_nack( GPIO_I2C_InitStruct );
        }
        else 
        {
            GPIO_I2C_send_ack( GPIO_I2C_InitStruct );
        }
    }
    
    GPIO_I2C_stop( GPIO_I2C_InitStruct );
    GPIO_I2C_InitStruct->busy_flag = false;
    
    return I2C_GPIO_Success;
}

/******************* (C) COPYRIGHT 2015 Realtek Semiconductor Corporation *****END OF FILE****/

